package org.datascooter.utils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.datascooter.bundle.DSMapper;
import org.datascooter.bundle.EntityBundle;
import org.datascooter.bundle.attribute.PersistAttribute;
import org.datascooter.exception.DataScooterException;
import org.datascooter.impl.DataSnip;
import org.datascooter.utils.policy.SnipType;

public class ChangeHolder {

	private Map<PersistAttribute, Object> valueMap = new HashMap<PersistAttribute, Object>();
	private final Object item;
	private EntityBundle bundle;

	public static ChangeHolder wrap(Object item) {
		try {
			return new ChangeHolder(item);
		} catch (Exception e) {
			throw new DataScooterException(e);
		}
	}

	public ChangeHolder(Object item) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		this.item = item;
		explore();
	}

	private void explore() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		bundle = DSMapper.getBundle(item);
		for (PersistAttribute attribute : bundle.attrArray) {
			Object value = attribute.getValue(item);
			valueMap.put(attribute, value);
		}
	}

	public DataSnip match() {
		DataSnip result = new DataSnip(bundle.entity, SnipType.UPDATE);
		boolean wasChanged = false;
		try {
			for (PersistAttribute attribute : bundle.attrArray) {
				Object newValue = attribute.getValue(item);
				Object oldValue = valueMap.get(attribute);
				if (!LangUtils.equalsAnyWay(oldValue, newValue)) {
					result.what(attribute.name, newValue);
					wasChanged = true;
				}
			}
			if (!wasChanged) {
				return null;
			}
			result.where(bundle.id.name, bundle.id.getValue(item));
		} catch (Exception e) {
			throw new DataScooterException(e);
		}
		return result;
	}

	public Map<PersistAttribute, Object> getValueMap() {
		return valueMap;
	}
}
